package com.ruoyi.quality.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.Defect;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.quality.domain.QualityPhysicalDefect;
import com.ruoyi.quality.domain.QualityPhysicalReport;
import com.ruoyi.quality.domain.bo.QualityPhysicalDefectBo;
import com.ruoyi.quality.domain.vo.QualityPhysicalDefectVo;
import com.ruoyi.quality.domain.vo.QualityPhysicalReportVo;
import com.ruoyi.quality.domain.vo.RecentHalfYearDefectVo;
import com.ruoyi.quality.mapper.QualityPhysicalDefectMapper;
import com.ruoyi.quality.mapper.QualityPhysicalReportMapper;
import com.ruoyi.quality.service.IQualityPhysicalDefectService;
import com.ruoyi.system.mapper.SysDictDataMapper;
import com.ruoyi.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.*;

import static com.ruoyi.common.Utils.getRecentHalfYearTimeRanges;

/**
 * 质量问题Service业务层处理
 *
 * @author ruoyi
 * @date 2023-07-31
 */
@RequiredArgsConstructor
@Service
public class QualityPhysicalDefectServiceImpl implements IQualityPhysicalDefectService {

    private final QualityPhysicalDefectMapper baseMapper;
    private final QualityPhysicalReportMapper reportMapper;
    private final ISysUserService userService;
    private final SysDictDataMapper sysDictDataMapper;
    /**
     * 查询质量问题
     */
    @Override
    public QualityPhysicalDefectVo queryById(Long defectId){
        return baseMapper.selectVoById(defectId);
    }

    /**
     * 查询质量问题
     */
    @Override
    public List<QualityPhysicalDefectVo> queryByIds(Collection<Long> defectIds){
        return baseMapper.selectVoBatchIds(defectIds);
    }

    /**
     * 查询质量问题
     */
    @Override
    public List<QualityPhysicalDefectVo> queryByReportIds(Collection<Long> reportIds) {
        List<QualityPhysicalDefectVo> qualityPhysicalDefectVoList = new ArrayList<>();
        for (Long reportId : reportIds) {
            QualityPhysicalReportVo reportVo = reportMapper.selectVoById(reportId);
            QualityPhysicalDefectBo defectBo = new QualityPhysicalDefectBo();
            defectBo.setReportId(reportId);
            LambdaQueryWrapper<QualityPhysicalDefect> lqw = buildQueryWrapper(defectBo);
            List<QualityPhysicalDefectVo> result = baseMapper.selectVoList(lqw);
            String reportName = reportVo.getReportName();
            String defectType;
            Date year = reportVo.getReportDate();
            if (reportName.equals(Defect.VALUE_PHYSICAL)){
                defectType = Defect.TYPE_TECHNOLOGY;
            }else{
                defectType = Defect.TYPE_PHYSICAL;
            }
            String reportNumber = reportVo.getReportNumber();
            result.forEach(item->{
                String partName = null;
                String contractNumber = null;
                SysUser user = null;
                try {
                    String userId = item.getWorkersId();
                    partName = item.getPartName();
                    String partNumber = item.getPartNumber();
                    contractNumber = StringUtils.matchNumber(partNumber);
                    user = userService.selectUserByUserName(userId);
                    item.setDefectClass(defectType);
                    item.setReportNumber(reportNumber);
                    item.setDeptFullName(reportVo.getDeptAbbreviation());
                    item.setCompanyId(user.getCompanyId());
                    item.setDateYear(year);
                    String newPartName = transferPartName(partName);
                    item.setNewPartName(newPartName);
                    item.setContractNumber(contractNumber);
                } catch (Exception e) {
                    throw new RuntimeException(reportNumber+"号通报获取信息失败");
                }
            });
            qualityPhysicalDefectVoList.addAll(result);
        }
        return qualityPhysicalDefectVoList;
    }

    public String transferPartName(String partName){
        List<String> arr = new ArrayList<>();
        List<SysDictData> sysDictData = sysDictDataMapper.selectDictDataByType("typical_workpiece");
        sysDictData.forEach(item->{
            String label = item.getDictLabel();
            arr.add(label);
        });
        String newPartName = partName.split("体")[0];
        boolean flag = arr.contains(newPartName);
        if (!flag){
            newPartName = Defect.TYPE_OTHER;
        }
        return newPartName;
    }

    /**
     * 查询质量问题列表
     */
    @Override
    public TableDataInfo<QualityPhysicalDefectVo> queryPageList(QualityPhysicalDefectBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<QualityPhysicalDefect> lqw = buildQueryWrapper(bo);
        Page<QualityPhysicalDefectVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询质量问题列表
     */
    @Override
    public List<QualityPhysicalDefectVo> queryList(QualityPhysicalDefectBo bo) {
        LambdaQueryWrapper<QualityPhysicalDefect> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 查询质量问题列表
     */
    @Override
    public List<RecentHalfYearDefectVo> getRecentHalfYearDefect(QualityPhysicalDefectBo bo) {
        LocalDate currentDate = LocalDate.now();
        List<Map<String, Object>> timeRanges = getRecentHalfYearTimeRanges(currentDate);

        List<RecentHalfYearDefectVo> result = new ArrayList<>();

        timeRanges.forEach(item -> {
            bo.setParams(item);
            LambdaQueryWrapper<QualityPhysicalDefect> lqw = buildQueryWrapper(bo);
            List<QualityPhysicalDefectVo> defectVos = baseMapper.selectVoList(lqw);
            int sum = defectVos.stream()
                .mapToInt(QualityPhysicalDefectVo::getDefectFine)
                .sum();

            RecentHalfYearDefectVo vo = new RecentHalfYearDefectVo();
            vo.setDate(String.valueOf(item.get("date")));
            vo.setDefectFine(Math.toIntExact(!defectVos.isEmpty() ? sum : 0L)); // 使用三元运算符进行空值处理
            vo.setDefectNumber(Math.toIntExact(!defectVos.isEmpty() ? defectVos.size() : 0L)); // 使用三元运算符进行空值处理

            result.add(vo);
        });

        return result;
    }

    private LambdaQueryWrapper<QualityPhysicalDefect> buildQueryWrapper(QualityPhysicalDefectBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<QualityPhysicalDefect> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getReportId() != null, QualityPhysicalDefect::getReportId, bo.getReportId());
        lqw.eq(StringUtils.isNotBlank(bo.getPartNumber()), QualityPhysicalDefect::getPartNumber, bo.getPartNumber());
        lqw.like(StringUtils.isNotBlank(bo.getPartName()), QualityPhysicalDefect::getPartName, bo.getPartName());
        lqw.eq(StringUtils.isNotBlank(bo.getDefectClassification()), QualityPhysicalDefect::getDefectClassification, bo.getDefectClassification());
        lqw.eq(bo.getWorkersId() != null, QualityPhysicalDefect::getWorkersId, bo.getWorkersId());
        lqw.like(StringUtils.isNotBlank(bo.getWorkersName()), QualityPhysicalDefect::getWorkersName, bo.getWorkersName());
        lqw.eq(StringUtils.isNotBlank(bo.getDefectPicture()), QualityPhysicalDefect::getDefectPicture, bo.getDefectPicture());
        lqw.eq(bo.getDefectFine() != null, QualityPhysicalDefect::getDefectFine, bo.getDefectFine());
        lqw.between(params.get("beginDate") != null && params.get("endDate") != null,
                QualityPhysicalDefect::getDefectDate ,params.get("beginDate"), params.get("endDate"));
        lqw.eq(StringUtils.isNotBlank(bo.getDeptAbbreviation()), QualityPhysicalDefect::getDeptAbbreviation, bo.getDeptAbbreviation());
        lqw.eq(bo.getDefectDate() != null, QualityPhysicalDefect::getDefectDate, bo.getDefectDate());
        lqw.orderByDesc(QualityPhysicalDefect::getDefectDate);
        return lqw;
    }

    /**
     * 新增质量问题
     */
    @Override
    public Boolean insertByBo(QualityPhysicalDefectBo bo) {
        QualityPhysicalDefect add = BeanUtil.toBean(bo, QualityPhysicalDefect.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setDefectId(add.getDefectId());
        }
        return flag;
    }

    /**
     * 修改质量问题
     */
    @Override
    public Boolean updateByBo(QualityPhysicalDefectBo bo) {
        QualityPhysicalDefect update = BeanUtil.toBean(bo, QualityPhysicalDefect.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 批量新增或修改质量问题
     */
    @Override
    public Boolean insertOrUpdateBatch(Collection<QualityPhysicalDefectBo> boList, Long reportId, Date reportDate) {
        Collection<QualityPhysicalDefect> insertOrUpdateList = new ArrayList<>();
        boList.forEach(s -> {
            QualityPhysicalDefect insertOrUpdate = BeanUtil.toBean(s, QualityPhysicalDefect.class);
            insertOrUpdate.setReportId(reportId);
            insertOrUpdate.setDefectDate(reportDate);
            insertOrUpdateList.add(insertOrUpdate);
        });
        return baseMapper.insertOrUpdateBatch(insertOrUpdateList);
    }



    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(QualityPhysicalDefect entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除质量问题
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 根据reportId删除质量问题
     */
    @Override
    public Boolean deleteWithValidByReportIds(List<Long> reportIds, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        boolean result = false;
        reportIds.forEach(item->{
            QualityPhysicalDefectBo bo = new QualityPhysicalDefectBo();
            bo.setReportId(item);
            LambdaQueryWrapper<QualityPhysicalDefect> lqw = buildQueryWrapper(bo);
            baseMapper.delete(lqw);
        });
        return result;
    }
}
